package org.finesys.system.controller;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.finesys.common.core.constants.RestApiConfig;
import org.finesys.common.core.module.R;
import org.finesys.common.log.core.annotation.LogAnnotation;
import org.finesys.common.log.core.enums.OperateType;
import org.finesys.system.api.entity.SysDict;
import org.finesys.system.api.entity.SysDictItem;
import org.finesys.system.constants.ControllerRestApiConfig;
import org.finesys.system.service.SysDictItemService;
import org.finesys.system.service.SysDictService;
import org.springframework.http.HttpHeaders;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;

@RestController
@RequiredArgsConstructor
@RequestMapping(value = ControllerRestApiConfig.DICT)
@Tag(name = "字典管理模块")
@SecurityRequirement(name = HttpHeaders.AUTHORIZATION)
public class SysDictController {

    private final SysDictService sysDictService;
    private final SysDictItemService sysDictItemService;

    @PostMapping(RestApiConfig.ADD)
    @Operation(summary = "新增")
    @LogAnnotation(title = "字典管理", operateType = OperateType.INSERT)
    @PreAuthorize("@pms.hasPermission('sys_dict_add')")
    public R<Boolean> add(@RequestBody SysDict sysDict) {
        return R.success(sysDictService.save(sysDict));
    }

    @PutMapping(RestApiConfig.UPDATE)
    @Operation(summary = "修改")
    @LogAnnotation(title = "字典管理", operateType = OperateType.UPDATE)
    @PreAuthorize("@pms.hasPermission('sys_dict_edit')")
    public R<Boolean> update(@RequestBody SysDict sysDict) {
        return R.judge(sysDictService.updateDict(sysDict));
    }


    @DeleteMapping(RestApiConfig.DELETE)
    @Operation(summary = "批量删除")
    @LogAnnotation(title = "字典管理", operateType = OperateType.DELETE)
    @PreAuthorize("@pms.hasPermission('sys_dict_del')")
    public R<Boolean> delete(@RequestBody Long[] ids) {
        return R.judge(sysDictService.removeDicts(ids));
    }

    @GetMapping(RestApiConfig.LIST)
    @Operation(summary = "根据名称或者类型查询")
    public R<List<SysDict>> findList(String name) {
        return R.success(sysDictService.list(Wrappers.<SysDict>lambdaQuery().like(StringUtils.isNotBlank(name), SysDict::getDictType, name)
                .or().like(StringUtils.isNotBlank(name), SysDict::getDescription, name)));
    }

    @GetMapping(RestApiConfig.PAGE)
    @Operation(summary = "分页")
    public R<IPage<SysDict>> getDictPage(Page<SysDict> sysDictPage, SysDict sysDict) {
        return R.success(sysDictService.findPage(sysDictPage, sysDict));
    }

    @GetMapping(RestApiConfig.GET + "/{id}")
    @Operation(summary = "获取单条")
    public R<SysDict> findById(@PathVariable Long id) {
        return R.success(sysDictService.getById(id));
    }

    @GetMapping(RestApiConfig.DETAILS)
    @Operation(summary = "获取单条")
    public R<SysDict> details(SysDict query) {
        return R.success(sysDictService.getOne(query));
    }


    @PostMapping(ControllerRestApiConfig.DICT_ITEM + RestApiConfig.ADD)
    @Operation(summary = "新增字典项")
    @LogAnnotation(title = "字典管理", operateType = OperateType.INSERT)
    public R<Boolean> addItem(@RequestBody SysDictItem sysDict) {
        return R.success(sysDictItemService.save(sysDict));
    }

    @PutMapping(ControllerRestApiConfig.DICT_ITEM + RestApiConfig.UPDATE)
    @Operation(summary = "修改字典项")
    @LogAnnotation(title = "字典管理", operateType = OperateType.UPDATE)
    public R<Boolean> updateItem(@RequestBody SysDictItem sysDictItem) {
        return R.judge(sysDictItemService.updateDictItem(sysDictItem));
    }


    @DeleteMapping(ControllerRestApiConfig.DICT_ITEM + RestApiConfig.DELETE)
    @Operation(summary = "批量删除字典项")
    @LogAnnotation(title = "字典管理", operateType = OperateType.DELETE)
    public R<Boolean> deleteItem(@PathVariable Long[] ids) {
        return R.judge(sysDictItemService.removeDictItems(ids));
    }

    @GetMapping(ControllerRestApiConfig.DICT_ITEM + RestApiConfig.PAGE)
    @Operation(summary = "分页字典项")
    public R<IPage<SysDictItem>> getDictItemPage(Page<SysDictItem> sysDictPage, SysDictItem sysDictItem) {
        return R.success(sysDictItemService.findPage(sysDictPage, sysDictItem));
    }

    @GetMapping(ControllerRestApiConfig.DICT_ITEM + RestApiConfig.GET + "/{id}")
    @Operation(summary = "获取单条字典项")
    public R<SysDictItem> findItemById(@PathVariable Long id) {
        return R.success(sysDictItemService.getById(id));
    }

    @GetMapping(ControllerRestApiConfig.DICT_ITEM + RestApiConfig.DETAILS)
    @Operation(summary = "获取单条")
    public R<SysDictItem> details(SysDictItem query) {
        return R.success(sysDictItemService.getOne(query));
    }

    /**
     * 通过字典类型查找字典
     *
     * @param type 类型
     * @return 同类型字典
     */
    @GetMapping("/type/{type}")
    public R<List<SysDictItem>> getDictByType(@PathVariable String type) {
        return R.success(sysDictItemService.findType(type));
    }

    /**
     * 通过字典类型查找字典
     *
     * @param type 类型
     * @return 同类型字典
     */
    @GetMapping("/findType/{type}")
    public R<List<Map<String, String>>> findDictByType(@PathVariable String type) {
        List<SysDictItem> sysDictItems = sysDictItemService.findType(type);
        List<Map<String, String>> resultMap = Lists.transform(sysDictItems, (dictItem) -> {
            Map<String, String> map = new HashMap<>();
            map.put("name", dictItem.getLabel());
            map.put("value", dictItem.getItemValue());
            return map;
        });

        return R.success(resultMap);
    }

    /**
     * 同步缓存字典
     *
     * @return R
     */
    @Operation(summary = "同步字典")
    @LogAnnotation(title = "同步字典", operateType = OperateType.CLEAN)
    @PutMapping(RestApiConfig.SYNC)
    public R<?> sync() {
        return sysDictService.sync();
    }
}
